﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;


namespace JBUtilities
{
    public class JBRichTextHighLighterCSharpTheme
    {
        private string _cSharpKeyWords = "\\b(abstract|as|base|bool|break|byte|case|catch|char|checked|class|const|continue|" +
                        "decimal|default|delegate|do|double|else|enum|event|explicit|extern|false|finally|" +
                        "fixed|float|for|foreach|goto|if|implicit|in|int|interface|internal|is|lock|long|" +
                        "namespace|new|null|object|operator|out|override|params|private|protected|public|" +
                        "readonly|ref|return|sbyte|sealed|short|sizeof|stackalloc|static|string|struct|" +
                        "switch|this|throw|true|try|typeof|uint|ulong|unchecked|unsafe|ushort|using|virtual|" +
                        "volatile|void|while)\\b";
        private string _lineComments = @"(\/\/.*)";
        private string _useClause = @"\b(using.*)\b";

        public JBRichTextHighLighterCSharpTheme()
        {
            _theme = new JBRichTextHighLighterTheme();
            _theme.FontDefault = new Font("System", 12, FontStyle.Regular);
            _theme.FontColorDefault = Color.Black;
            _theme.BackgroundColorDefault = Color.WhiteSmoke;
            JBRichTextHighLighterDefinition def1 = new JBRichTextHighLighterDefinition();
            def1.KeyWords = _cSharpKeyWords;
            def1.FontColorHighLighted = Color.Navy;
            def1.BackgroundHighLighted = Color.WhiteSmoke;
            def1.FontHighLighted = new Font("System", 12, FontStyle.Bold);
            _theme.Definitions.Add(def1);
            JBRichTextHighLighterDefinition def2 = new JBRichTextHighLighterDefinition();
            def2.KeyWords = _lineComments;
            def2.FontColorHighLighted = Color.Gray;
            def2.BackgroundHighLighted = Color.WhiteSmoke;
            def2.FontHighLighted = new Font("System", 12, FontStyle.Italic);
            _theme.Definitions.Add(def2);
            JBRichTextHighLighterDefinition def3 = new JBRichTextHighLighterDefinition();
            def3.KeyWords = _useClause;
            def3.FontColorHighLighted = Color.Green;
            def3.BackgroundHighLighted = Color.WhiteSmoke;
            def3.FontHighLighted = new Font("System", 12, FontStyle.Bold & FontStyle.Underline);
            _theme.Definitions.Add(def3);

        }
        private JBRichTextHighLighterTheme _theme ;
        public JBRichTextHighLighterTheme Theme
        {
            get
            {
                return _theme;
            }
        }
    }
    public class JBRichTextHighLighterTheme
    {
        private List<JBRichTextHighLighterDefinition> _definitions;
        private Font _fontDefault;
        private Color _fontColorDefault;
        private Color _backgroundColorDefault;
        public JBRichTextHighLighterTheme()
        {
            _definitions = new List<JBRichTextHighLighterDefinition>();
        }
        public Font FontDefault
        {
            get { 
                return _fontDefault; 
            }
            set {
                _fontDefault = value;
            }
        }
        public Color FontColorDefault
        {
            get
            {
                return _fontColorDefault;
            }
            set
            {
                _fontColorDefault = value;
            }
        }
        public Color BackgroundColorDefault
        {
            get
            {
                return _backgroundColorDefault;
            }
            set
            {
                _backgroundColorDefault = value;
            }
        }
        public List<JBRichTextHighLighterDefinition> Definitions
        {
            get 
            {
                return _definitions;
            }
            set 
            {
                _definitions = value;
            }
        }
    }

    public class JBRichTextHighLighterDefinition
    { 
        private string _keyWords;
        public string KeyWords 
        {
            get
            {
                return _keyWords;
            }
            set
            {
                _keyWords = value;
                createRegEx(_keyWords);
            } 
        }
        public Color FontColorDefault = Color.Black;
        public Color FontColorHighLighted = Color.Navy;
        public Font FontDefault = new Font("System", 12, FontStyle.Bold);
        public Font FontHighLighted = new Font("System", 12, FontStyle.Bold);
        public Color BackgroundDefault = Color.WhiteSmoke;
        public Color BackgroundHighLighted = Color.WhiteSmoke;
        private Regex _regEx;
        private void createRegEx(string value)
        {
            _regEx = new Regex(value);
        }
        public Regex getRegEx()
        {
            return _regEx;
        }
    }

    public class JBRichTextHighLighter
    {
        [DllImport("user32.dll")] 
        public static extern bool LockWindowUpdate(IntPtr hWndLock);
        private RichTextBox _richTextBox = null;
        private JBRichTextHighLighterTheme _theme;
        public JBRichTextHighLighterTheme Theme
        {
            get
            {
                return _theme;
            }
            set
            {
                _theme = value;
                UdpateRichTextSettings();
            }
        }
        private void UdpateRichTextSettings()
        {
                if ((RichTextBox != null)&&(Theme!=null))
                {
                    _richTextBox.SelectionColor = _theme.FontColorDefault;
                    _richTextBox.SelectionBackColor = _theme.BackgroundColorDefault;
                    _richTextBox.SelectionFont = _theme.FontDefault;
                    _richTextBox.BackColor = _theme.BackgroundColorDefault;
                    _richTextBox.Font = _theme.FontDefault; 
                    _richTextBox.ForeColor = _theme.FontColorDefault;
                }
        }
        public JBRichTextHighLighter(RichTextBox richTextBox)
        {
            RichTextBox = richTextBox;
            UdpateRichTextSettings();
        }

        public RichTextBox RichTextBox
        {
            get {
                return _richTextBox;
            }
            set {
                _richTextBox = value;
                addEventHandler();
                UdpateRichTextSettings();
            }
        }

        private void addEventHandler()
        { 
               // _richTextBox.SelectionChanged += new EventHandler(OnTextChanged);
                //_richTextBox.VScroll += new EventHandler(OnScrolled);
                //_richTextBox.HScroll += new EventHandler(OnScrolled);
                _richTextBox.TextChanged += new EventHandler(OnTextChanged);
        }
        private void removeEventHandler()
        {
            //_richTextBox.SelectionChanged -= new EventHandler(OnTextChanged);
            //_richTextBox.VScroll -= new EventHandler(OnScrolled);
            //_richTextBox.HScroll -= new EventHandler(OnScrolled);
            _richTextBox.TextChanged -= new EventHandler(OnTextChanged);
        }

        private string getVisibleLines(ref int startIndex,ref int length)
        { 
            startIndex = _richTextBox.GetCharIndexFromPosition(new Point(0, 0));
            int endIndex = _richTextBox.GetCharIndexFromPosition(new Point(_richTextBox.Width, _richTextBox.Height));
            length = (endIndex>startIndex?endIndex-startIndex:0);
            //return _richTextBox.Rtf.Substring(startIndex, length);
            return _richTextBox.Text.Substring(startIndex, length);
        }

        private void OnTextChanged(object sender, EventArgs e)
        {
            try
            {
                LockWindowUpdate(_richTextBox.Handle);
                removeEventHandler();
                int sPos = _richTextBox.SelectionStart;
                int sLength = _richTextBox.SelectionLength;
                int startIndex = 0;
                int length = 0;
                //string text = getVisibleLines(ref startIndex, ref length);
                string text = _richTextBox.Text;
                _richTextBox.SelectAll();
                _richTextBox.SelectionColor = Theme.FontColorDefault;
                _richTextBox.SelectionBackColor = Theme.BackgroundColorDefault;
                _richTextBox.SelectionFont = Theme.FontDefault;
                _richTextBox.SelectionStart = sPos;

                foreach (JBRichTextHighLighterDefinition def in Theme.Definitions)
                {
                    foreach (Match keyWordMatch in def.getRegEx().Matches(text))
                    {
                        _richTextBox.Select(startIndex + keyWordMatch.Index, keyWordMatch.Length);
                        _richTextBox.SelectionColor = def.FontColorHighLighted;
                        _richTextBox.SelectionBackColor = def.BackgroundHighLighted;
                        _richTextBox.SelectionFont = def.FontHighLighted;
                    }
                }
                _richTextBox.SelectionStart = sPos;
                _richTextBox.SelectionLength = sLength;
                _richTextBox.Select();

            }
            finally
            {
                LockWindowUpdate(IntPtr.Zero);
                addEventHandler();
            }

        }


    }
}

